#pragma once

#include"Socket.hpp"
#include"InetAddr.hpp"
#include<memory>
#include<unistd.h>
#include<iostream>
#include<signal.h>
#include<functional>

using callback_t = std::function<std::string(std::string &)>;//引用传参

class TcpServer
{
public:
    TcpServer(uint16_t port , callback_t cb)
    :_port(port)
    ,_listensockfd(std::make_shared<TcpSocket>())
    ,_cb(cb)
    {
        //在构造的时候创建监听套接字
        _listensockfd->BulidListenSocketMethod(_port);
    }

    void HandlerRequest(std::shared_ptr<Socket> sockfd , InetAddr addr)
    {
        std::string inbuffer;//接收缓冲区
        while(true)
        {
            //从接收缓冲区中读取数据，如何得知自己的数据是否读取完整-->协议
            ssize_t n = sockfd->Recv(&inbuffer);
            if(n > 0)
            {
                LOG(LogLevel::DEBUG) <<  addr.ToString() <<"# " <<inbuffer;
                //将读取到的数据回调出去进行处理
                std::string send_str = _cb(inbuffer);
                if(send_str.empty()) continue;
                LOG(LogLevel::DEBUG) << "send_str: " << send_str;

                sockfd->Send(send_str);
            }
            else if(n==0)
            {
                //意味着客户端退出
                LOG(LogLevel::DEBUG) << addr.ToString() <<" ,client 退出， 服务器端也退出";
                break; 
            }
            else
            {
                LOG(LogLevel::DEBUG) << addr.ToString() << " read error , quit~";
                break; 
            }
        }
        sockfd->Close();
    }
    //让服务器运行起来
    void Run()
    {
        //父进程忽略对子进程的等待信号
        signal(SIGCHLD, SIG_IGN);
        //服务器是一个死循环
        //获取连接、指定协议的读、写
        while(true)
        {
            InetAddr addr;
            std::shared_ptr<Socket> sockfd = _listensockfd->Accept(&addr);
            //判断获取连接是否成功
            if(sockfd == nullptr) continue;
            LOG(LogLevel::DEBUG) << "获取一个新连接" << addr.ToString() << ", sockfd : " << sockfd->Sockfd();

            //创建子进程进行IO
            if(fork()==0)
            {
                //子进程关闭不用的文件描述符
                _listensockfd->Close();
                HandlerRequest(sockfd , addr);//处理IO
                exit(0);
            }
            //父进程也需要关闭不用的文件描述符
            sockfd->Close();

        }        
    }
    ~TcpServer()
    {}
private:
    uint16_t _port;
    //套接字
    std::shared_ptr<Socket> _listensockfd;
    callback_t _cb;
};